#define MSSIGNAL_C
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h> 
#include <execinfo.h>
#include <libmslog/mslog.h>
#include "mscommon.h"
#include "mstime.h"
#include "mssignal.h"

#define FLAG "SIGNAL"

#define BACKTRACE_SIZE 20

static ms_byte file_signal[1024]={0};

ms_string mssignal_desstring[128]={
		"Unknow",
		"Hangup",
		"Interrupt",
		"Quit",
		"Illegal instruction",
		"Trace trap",
		"Abort  / IOT trap",
		"BUS error",
		"Floating-point exception",
		"Kill, unblockable",
		"User-defined signal 1",
		"Segmentation violation",
		"User-defined signal 2",
		"Broken pipe",
		"Alarm clock",
		"Termination",
		"Stack fault. ",
		"Same as SIGCHLD. Child status has changed ",
		"Continue ",
		"Stop, unblockable",
		"Keyboard stop",
		"Background read from tty",
		"Background write to tty ",
		"Urgent condition on socket",
		"CPU limit exceeded ",
		"File size limit exceeded",
		"Virtual alarm clock",
		"Profiling alarm clock ",
		"Window size change",
		"Pollable event occurred / I/O now possible ",
		"Power failure restart ",
		"Bad system call."		
	};
static ms_void mssignal_innerapi_handler(ms_s32 ms_in signum)
{   
	ms_byte msg[1024]={0};
	ms_logfileMsg(file_signal, msg, "================Catch a signal-1(%d):%s",signum,mssignal_desstring[signum]);
	ms_info("%s",msg);
}
static ms_void mssignal_innerapi_handler2(ms_s32 ms_in signum)
{   
	ms_byte msg[1024]={0};
	ms_logfileMsg(file_signal, msg, "================Catch a signal-2(%d):%s",signum,mssignal_desstring[signum]);
	ms_info("%s",msg);
/* 恢复信号默认处理 */
	signal(signum, SIG_DFL); 	 
/* 重新发送信号 */
    raise(signum);  	
}
static ms_void mssignal_innerapi_backTrace(ms_s32 ms_in signum)
{   
/*获取当前时间*/
	ms_byte strCurDTime[64]={0};
	mstime_api_curDTime(mstime_fmt_datetime_ex3, strCurDTime);
/*标记开头*/	
	ms_byte msg[1024]={0};
	ms_logfileMsg(file_signal, msg, "================Catch a signal-3(%d):%s,CurDTime:%s",signum,mssignal_desstring[signum],strCurDTime);
/*获取MAP信息*/	
	ms_info("%s", msg);
	ms_cmd(msg,"cat /proc/%d/maps > %s", getpid(),file_signal,strCurDTime);  
/*获取BACKTRACE信息*/		
	void *buffer[BACKTRACE_SIZE];  
    int nptrs = backtrace(buffer, BACKTRACE_SIZE);  
	ms_logfileMsg(file_signal, msg,"backtrace() returned %d addresses", nptrs); 
	ms_info("%s", msg);
    char **strings = backtrace_symbols(buffer, nptrs);  
    if (strings == ms_null) {  
        ms_errExit(EXIT_FAILURE,"backtrace_symbols");  
	}  
    for (int j = 0; j < nptrs; j++){  
		ms_logfileMsg(file_signal, msg,"[%02d] %s", j, strings[j]);  
		ms_info("%s", msg);
    }
    free(strings);  
/* 恢复信号默认处理 */
	signal(signum, SIG_DFL); 	 
/* 重新发送信号 */
    raise(signum);  			  
}

static ms_void mssignal_innerapi_set(ms_s32 ms_in signum,ms_void (*handler)(ms_s32 ms_in signum))
{
	struct sigaction action;
	if(ms_null==handler){
		action.sa_handler = SIG_IGN;
	}else{
		action.sa_handler = handler;
	}
	action.sa_flags = 0;
	if (sigemptyset(&action.sa_mask)  <0) {
		ms_error("sigemptyset failed");
	}
	if (sigaction(signum, &action, 0)  <0) {
		ms_error("sigaction failed");
	}
}

static ms_void mssignal_innerapi_sigMask(ms_s32 ms_in signum)
{
	sigset_t signal_mask;
	sigemptyset (&signal_mask);
	sigaddset (&signal_mask, signum);
	if (pthread_sigmask (SIG_BLOCK, &signal_mask, NULL) <0) {
		ms_error("pthread_sigmask failed:block sigpipe error");
	}
	if (sigprocmask (SIG_BLOCK, &signal_mask, NULL) <0) {
		ms_error("sigprocmask failed:block sigpipe error");
	}
}

ms_void mssignal_api_catch(ms_string name)
{
#if defined(OS_ANDROID)||defined(OS_LINUX_SOC)	
	ms_sprintfs(file_signal, "/var/log/mscore/signal_%s.txt", name);
	sigset_t signal_mask;
	sigemptyset (&signal_mask);
	sigaddset (&signal_mask, SIGPIPE);
	int rc = pthread_sigmask (SIG_BLOCK, &signal_mask, NULL);
	if (rc != 0) {
		ms_error("pthread_sigmask failed:block sigpipe error");
	}
	//SIG_ERR,SIG_IGN,SIG_DFL,func_handle
	signal(SIGHUP		, SIG_IGN); 		//signal:Hangup -terminal shutdown	stop 
	signal(SIGTTIN		, mssignal_innerapi_handler);   	//signal:Interrupt-"ctrl+c" or "delete"	stop
	signal(SIGQUIT		, mssignal_innerapi_handler);	//signal:Quit-"ctrl+\" interrupt		stop, and create a core file
	signal(SIGILL		, mssignal_innerapi_handler);	//signal:illegal instruction			create a core file
	signal(SIGTRAP		, mssignal_innerapi_handler);	//signal:Trace trap				create a core file
	signal(SIGABRT		, mssignal_innerapi_handler);	//signal:Abort					create a core file	
	signal(SIGIOT		, mssignal_innerapi_handler);	//signal:IOT trap				create a core file	
	signal(SIGBUS		, mssignal_innerapi_handler);	//signal:bus error 				create a core file
	signal(SIGFPE		, mssignal_innerapi_handler);	//signal:Floating-point exception		create a core file	
	signal(SIGKILL		, mssignal_innerapi_handler2);		//signal:Kill, unblockable			stop	
	signal(SIGUSR1		, mssignal_innerapi_handler);	//signal:User-defined signal 1		stop
	signal(SIGSEGV		, mssignal_innerapi_backTrace);		//signal:Segmentation violation		create a core file	
	signal(SIGUSR2		, mssignal_innerapi_handler);	//signal:User-defined signal 2		stop	
#if 0	
	signal(SIGPIPE		, mssignal_innerapi_handler);	//signal:Broken pipe				stop
#else
	//signal(SIGPIPE		, SIG_IGN);	//signal:Broken pipe				stop
	mssignal_innerapi_sigMask(SIGPIPE);
	mssignal_innerapi_set(SIGPIPE, ms_null);
#endif
	signal(SIGALRM	, mssignal_innerapi_handler);	//signal:Alarm clock				stop
	signal(SIGTERM	, mssignal_innerapi_handler);	//signal:Termination				stop	
	signal(SIGSTKFLT	, mssignal_innerapi_handler);	//signal:Stack fault				stop	
/* BEGIN: Added by su.gao<sugao_cn@163.com>, 2016/12/27 ,to ret 1, when call system*/
#if defined(OS_LINUX_SOC)
	//signal(SIGCLD		, SIG_IGN);		//signal:Same as SIGCHLD			ignor	
#endif
	//如使用system命令后，会收到该信号
	signal(SIGCHLD	, SIG_DFL);		//signal:Child status has changed		ignor	
/* END:   Added by su.gao<sugao_cn@163.com>, 2016/12/27 */
	signal(SIGCONT	, mssignal_innerapi_handler);	//signal:Continue				ignor	
	signal(SIGSTOP		, mssignal_innerapi_handler);	//signal:Stop, unblockablel			stop
	signal(SIGTSTP		, mssignal_innerapi_handler);	//signal:Keyboard stop-"ctrl+z"		stop	
	signal(SIGTTIN		, SIG_IGN);	//signal:Background read from tty 	stop	
	signal(SIGTTOU	, SIG_IGN);	//signal:Background write to tty		stop	
	signal(SIGURG		, mssignal_innerapi_handler);	//signal:Urgent condition on socket	ignor	
	signal(SIGXCPU	, mssignal_innerapi_handler);	//signal:CPU limit exceeded		stop
	signal(SIGXFSZ		, mssignal_innerapi_handler);	//signal:File size limit exceeded		stop
	signal(SIGVTALRM	, mssignal_innerapi_handler);	//signal:Virtual alarm clock			stop
	signal(SIGPROF	, mssignal_innerapi_handler);	//signal:Profiling alarm clock		stop	
	signal(SIGWINCH	, SIG_IGN);		//signal:Window size change		ignor	
	signal(SIGPOLL		, mssignal_innerapi_handler);	//signal:Pollable event occurred		ignor
	signal(SIGIO		, mssignal_innerapi_handler);	//signal:I/O now possible			ignor
	signal(SIGPWR		, mssignal_innerapi_handler);	//signal:Power failure restart		
	signal(SIGSYS		, mssignal_innerapi_handler);	//signal: Bad system call	
#else
	ms_funcNosupports;
#endif
}

#undef MSSIGNAL_C
